#include "bitmap.h"
#include "string.h"

void bitmap_init(bitmap* bmap){
	memset(bmap->bits,bmap->bmap_bytes_len,0);
}

uint8_t bitmap_test(bitmap* bmap,uint32_t bit_idx){
	uint32_t byte_start = bit_idx/8;
	uint32_t bits_offset = bit_idx%8;
	return bmap->bits[byte_start] & BITMAP_MASK<<bits_offset ? 1 : 0;
}

int32_t bitmap_scan(bitmap* bmap,uint32_t cnt){
	uint32_t i=0,j;
	uint8_t found_cnt;
	while(bmap->bits[i]==0xff && i<bmap->bmap_bytes_len){
		i++;
	}
	
	//all page is takened
	if(i==bmap->bmap_bytes_len){
		return -1;
	}else{
		//found the bit start index
		i<<=3;	
		for(j=0;j<8;j++){
			if(!bitmap_test(bmap,i+j))
				break;
		}
		//now i bits index is empty scan from here
		i+=j;
		if(cnt==1){
			//caller only want one
			return i;
		}
		found_cnt=1;
		//found successive cnt page for caller
		while(found_cnt<cnt && i<bmap->bmap_bytes_len*8){
			if(!bitmap_test(bmap,++i))
				found_cnt++;
			else
				found_cnt=0;
		}
		if(found_cnt==cnt){
			//index from start
			return i-cnt+1;
		}else{
			return -1;
		}
	}
}

void bitmap_set(bitmap* bmap,uint32_t bit_idx,int8_t v){
	uint32_t byte_start = bit_idx/8;
	uint32_t bits_offset = bit_idx%8;
	if(v){
		bmap->bits[byte_start] |= BITMAP_MASK<<bits_offset;
	}else{
		bmap->bits[byte_start] &= ~(BITMAP_MASK<<bits_offset);
	}
}
